from sanic import Sanic
from sanic.response import text
from sanic.response import json
import requests
import cv2
import base64
import time
import json as Json
import re
import difflib
import numpy as np
import os
from datetime import datetime
from table_ceil import table # 表格检测
from utils import draw_boxes
from pd_ocr import ocr_predict, SyncPredict # 文本识别
from slice_table import slice_table # 版面分析
from handle_cny import ChangeCNY # 人民币大小写转换
from sanic.log import logger
from paddleocr import PaddleOCR


app = Sanic("table-server")
ocr = PaddleOCR(cls_thresh=0, use_gpu=True, 
                        det_model_dir='./inference/ch_ppocr_server_v2.0_det_infer', 
                        rec_model_dir='./inference/ch_ppocr_server_v2.0_rec_infer', 
                        cls_model_dir='./inference/ch_ppocr_mobile_v2.0_cls_infer')
app.config.setdefault('ocr', ocr)


@app.post("/table/predict")
async def hello_world(request):
    res = {
        'msg': 'ok',
        'code': 0,
        'data': {}
    }
    if len(request.files.keys()) != 1:
        res['msg'] = '必须传入一个图片'
        res['code'] = 1
        return json(res)
    f = request.files.get(list(request.files.keys())[0])
    current_dir = os.getcwd()
    ceil_dir = os.path.join(os.path.join(current_dir, 'ceil-result'), datetime.now().strftime('%Y-%m-%d'))
    excel_dir = os.path.join(os.path.join(current_dir, 'excel-result'), datetime.now().strftime('%Y-%m-%d'))
    ceil_name = '%sceil.jpg' % os.path.splitext(f.name)[0]
    excel_name = '%s.xlsx' % os.path.splitext(f.name)[0]
    if not os.path.exists(ceil_dir):
        os.makedirs(ceil_dir, exist_ok=True)
        os.chmod(ceil_dir, mode=0o755)
    if not os.path.exists(excel_dir):
        os.makedirs(excel_dir, exist_ok=True)
        os.chmod(excel_dir, mode=0o755)
    ceil_img_path = os.path.join(ceil_dir, ceil_name)
    excel_path = os.path.join(excel_dir, excel_name)
    isToExcel = request.form.get('isToExcel')
    isToCeil = request.form.get('isToCeil')
    input_img = cv2.imdecode(np.frombuffer(f.body, np.uint8), cv2.IMREAD_COLOR)
    table_img, label_img, msg = slice_table(input_img)
    file_name = os.path.splitext(f.name)[0]
    tableDetect = table(input_img,tableSize=[416,416],
                        tableLineSize=[1024,1024],
                        isTableDetect=False,
                        isToExcel=True,
                        ocr=app.config['ocr'],
                        file_name=file_name
                        )
    # file_name=os.path.splitext(f.name)[0]
    tableJson = tableDetect.res
    row_data = {}
    draft_data = {
        'draftNo': '',
        'draftStatus': '',
        'draftDate': '',
        'expireDate': '',
        'drawerName': '',
        'drawerAccount': '', # 出票人
        'drawerBank': '',
        'takerName': '', # 收款人
        'takerAccount': '',
        'takerBank': '',
        'acceptorName': '', # 承兑人
        'acceptorAccount': '',
        'acceptorBank': '',
        'acceptorCnapscode': '',
        'drawerguarantorName': '', # 出票保证信息
        'drawerguarantorAddress': '',
        'drawerguarantorDate': '',
        'amount': '', # 金额
        'amountCh': '', # 金额大写
        'isTransfer': True,
        'promiseAcceptor': '', # 承兑人承诺
        'promiseDrawer': '', # 出票人承诺
        'promiseAcceptorDate': '', # 承兑日期
        'acceptguarantorName': '', # 承兑保证信息
        'acceptguarantorAddress': '',
        'acceptguarantorDate': '',
        'contractNumber': '', # 交易合同号
    }
    for col in tableJson:
        insert_value = col['text']
        remove_strs = ['大写', '人民币', '(', ')', '（', '）']
        for item in remove_strs:
            if item in insert_value:
                insert_value = insert_value.replace(item, '')
        if col['row'][1] - col['row'][0] > 1:
            for i in range(col['row'][0], col['row'][1]):
                key = '%s-%s' % (i, i + 1)
                if key not in row_data:
                    row_data[key] = insert_value
                else:
                    row_data[key] += insert_value
        else:
            key = '%s-%s' % (col['row'][0], col['row'][1])
            if key not in row_data:
                row_data[key] = insert_value
            else:
                row_data[key] += insert_value
    # handle draft meta data
    if not label_img is None:
        label_res = ocr_predict([label_img], ocr=app.config['ocr'], file_name=file_name, label=True)
        for info in label_res:
            new_s = info.replace(' ', '')
            new_s = new_s.replace(':', '')
            new_s = new_s.replace('：', '')
            logger.debug(new_s)
            if ('票据号码' in new_s and new_s != '票据号码') or (len(new_s) == 30 and new_s.isnumeric()):
                draft_data['draftNo'] = new_s.replace('票据号码', '')
            if ('票据状态' in new_s and new_s != '票据状态'):
                draft_data['draftStatus'] = new_s.replace('票据状态', '')
            if ('出票日期' in new_s and new_s != '出票日期'):
                draft_data['draftDate'] = new_s.replace('出票日期', '')
            if ('汇票到期日' in new_s and new_s != '汇票到期日'):
                draft_data['expireDate'] = new_s.replace('汇票到期日', '')
    is_handle = []
    for item in row_data.items():
        try:
            logger.debug(item)
            if item[0] in is_handle:
                continue
            if '评论' in item[1] or '评级' in item[1]:
                is_handle.append(item[0])
                continue
            # 处理票据金额
            if '票据金额' in item[1] or '票面金额' in item[1]:
                if draft_data['amountCh'] != '':
                    is_handle.append(item[0])
                    continue
                new_s = item[1].replace('票据金额', '')
                new_s = new_s.replace('票面金额', '')
                if '整' in new_s:
                    new_s = new_s.split('整')[0] + '整'
                    draft_data['amountCh'] = new_s
                elif '角' in new_s:
                    new_s = new_s.split('角')[0] + '角'
                    draft_data['amountCh'] = new_s
                elif '分' in new_s:
                    new_s = new_s.split('分')[0] + '分'
                    draft_data['amountCh'] = new_s
                elif '元' in new_s:
                    new_s = new_s.split('元')[0] + '元整'
                    draft_data['amountCh'] = new_s
                if draft_data['amountCh']:
                    draft_data['amount'] = ChangeCNY().big_to_small(draft_data['amountCh'])
            # 保存是否转让
            if '转让' in item[1]:
                if draft_data['isTransfer'] != '':
                    is_handle.append(item[0])
                    continue
                new_s = item[1].split('能否转让')[1]
                if '不' in new_s:
                    draft_data['isTransfer'] = False
            # 保存出票保证信息
            if '出票保证信息' in item[1]:
                new_s = item[1].replace('承兑保证信息', '')
                draft_data['acceptguarantorDate'] = new_s.split('保证日期：')[1]
                new_s = new_s.split('保证日期：')[0]
                draft_data['acceptguarantorAddress'] = new_s.split('保证人地址：')[1]
                new_s = new_s.split('保证人地址：')[0]
                draft_data['acceptguarantorName'] = new_s.split('保证人名称：')[1]
            # 保存承兑保证信息
            if '承兑保证信息' in item[1]:
                new_s = item[1].replace('承兑保证信息', '')
                draft_data['acceptguarantorDate'] = new_s.split('保证日期：')[1]
                new_s = new_s.split('保证日期：')[0]
                draft_data['acceptguarantorAddress'] = new_s.split('保证人地址：')[1]
                new_s = new_s.split('保证人地址：')[0]
                draft_data['acceptguarantorName'] = new_s.split('保证人名称：')[1]
            if '出票人全称' in item[1]:
                if '收款人全称' in item[1] and draft_data['drawerName'] == '':
                    draft_data['takerName'] = item[1].split('收款人全称')[1]
                    draft_data['drawerName'] = item[1].split('收款人全称')[1].replace('出票人全称', '')
                elif '收票人全称' in item[1] and draft_data['drawerName'] == '':
                    draft_data['takerName'] = item[1].split('收票人全称')[1]
                    draft_data['drawerName'] = item[1].split('收票人全称')[1].replace('出票人全称', '')
            if '出票人收款人' in item[1] and item[1].count('账号') > 1:
                new_s = item[1].replace('出票人收款人', '')
                draft_data['drawerAccount'] = new_s.split('账号')[1]
                draft_data['takerAccount'] = new_s.split('账号')[2]
            if '出票人收款人' in item[1] and item[1].count('开户银行') > 1:
                new_s = item[1].replace('出票人收款人', '')
                draft_data['drawerBank'] = new_s.split('开户银行')[1]
                draft_data['takerBank'] = new_s.split('开户银行')[2]
            if '承兑人信息' in item[1]:
                new_s = item[1].replace('承兑人信息', '')
                print(new_s)
                if draft_data['acceptorBank'] == '':
                    draft_data['acceptorBank'] = new_s.split('开户行名称')[1]
                if draft_data['acceptorAccount'] == '':
                    draft_data['acceptorAccount'] = new_s.split('开户行名称')[0].split('账号')[1]
                if draft_data['acceptorName'] == '':
                    draft_data['acceptorName'] = new_s.split('开户行名称')[0].split('账号')[0].split('全称')[1]
                if draft_data['acceptorCnapscode'] == '':
                    draft_data['acceptorCnapscode'] = new_s.split('开户行行号')[1]
                if draft_data['acceptorAccount'] == '':
                    draft_data['acceptorAccount'] = new_s.split('开户行行号')[0].split('账号')[1]
                if draft_data['acceptorName'] == '':
                    draft_data['acceptorName'] = new_s.split('开户行行号')[0].split('账号')[0].split('全称')[1]
        except Exception as e:
            logger.error(f'happen error {e}')
            continue
        finally:
            is_handle.append(item[0])
    logger.debug(draft_data)
    if isToCeil:
        img = tableDetect.img
        tmp = np.zeros_like(img)
        img = draw_boxes(tmp, tableDetect.tableCeilBoxes, color=(255, 255, 255))
        cv2.imwrite(ceil_img_path, img)
    # if isToExcel and tableDetect.workbook is not None:
    # if tableDetect.workbook is not None:
    #     tableDetect.workbook.save(excel_path)
    # get sync data
    # label_res = new_q.get()
    # if label_res:
    #     for info in label_res:
    #         new_s = info.replace(' ', '')
    #         new_s = new_s.replace(':', '')
    #         new_s = new_s.replace('：', '')
    #         logger.debug(new_s)
    #         if ('票据号码' in new_s and new_s != '票据号码') or (len(new_s) == 30 and new_s.isnumeric()):
    #             draft_data['draftNo'] = new_s.replace('票据号码', '')
    #         if ('票据状态' in new_s and new_s != '票据状态'):
    #             draft_data['draftStatus'] = new_s.replace('票据状态', '')
    #         if ('出票日期' in new_s and new_s != '出票日期'):
    #             draft_data['draftDate'] = new_s.replace('出票日期', '')
    #         if ('汇票到期日' in new_s and new_s != '汇票到期日'):
    #             draft_data['expireDate'] = new_s.replace('汇票到期日', '')
    res['data'] = draft_data
    return json(res)


if __name__ == "__main__":
    app.run(host='0.0.0.0', port='18083', debug=False)